import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Post,
  Query,
  BadRequestException,
} from '@nestjs/common';
import {
  ApiBody,
  ApiOperation,
  ApiParam,
  ApiQuery,
  ApiTags,
} from '@nestjs/swagger';
import { CloudinaryService } from '../services/cloudinary.service';
import { UploadImageDto } from '../dto/upload-image.dto';
import { UploadFolderDto } from '../dto/upload-folder.dto';
import { ExtractImagesDto } from '../dto/extract-images.dto';

// 定义接口类型
interface UploadResponse {
  public_id: string;
  secure_url: string;
  format: string;
  width: number;
  height: number;
  resource_type: string;
  [key: string]: any;
}

interface UrlResponse {
  url: string;
}

interface DeleteResponse {
  result: string;
  [key: string]: any;
}

interface ResourceDetails {
  public_id: string;
  format: string;
  resource_type: string;
  secure_url: string;
  created_at: string;
  [key: string]: any;
}

interface ExtractImagesResponse {
  images: string[];
  count: number;
}

@ApiTags('cloudinary')
@Controller('cloudinary')
export class CloudinaryController {
  constructor(private readonly cloudinaryService: CloudinaryService) {}

  /**
   * 上传图片
   * @param body 请求体，包含图片路径和上传选项
   * @returns 上传结果
   */
  @ApiOperation({
    summary: '上传图片',
    description: '上传图片到 Cloudinary 服务',
  })
  @ApiBody({
    type: UploadImageDto,
    description: '上传图片请求体',
    examples: {
      example1: {
        summary: '上传本地图片',
        value: {
          filePath: 'E:/images/sample.jpg',
          options: {
            public_id: 'sample_image',
            folder: 'samples',
            resource_type: 'image',
          },
        },
      },
      example2: {
        summary: '上传网络图片',
        value: {
          filePath: 'https://example.com/image.jpg',
          options: {
            folder: 'web_images',
          },
        },
      },
    },
  })
  @Post('upload')
  async uploadImage(@Body() body: UploadImageDto): Promise<UploadResponse> {
    if (!body.filePath) {
      throw new BadRequestException('filePath是必需的参数');
    }
    return this.cloudinaryService.uploadImage(body.filePath, body.options);
  }

  /**
   * 获取优化的图片 URL
   * @param publicId 图片的 public_id
   * @param query 查询参数，包含转换选项
   * @returns 优化后的图片 URL
   */
  @ApiOperation({
    summary: '获取优化的图片 URL',
    description: '根据 public_id 获取优化后的图片 URL',
  })
  @ApiParam({ name: 'publicId', description: '图片的 public_id' })
  @ApiQuery({
    name: 'fetch_format',
    required: false,
    description: '图片格式，默认为 auto',
  })
  @ApiQuery({
    name: 'quality',
    required: false,
    description: '图片质量，默认为 auto',
  })
  @Get('optimize/:publicId')
  getOptimizedUrl(
    @Param('publicId') publicId: string,
    @Query() query: Record<string, any>,
  ): UrlResponse {
    return {
      url: this.cloudinaryService.getOptimizedUrl(publicId, query),
    };
  }

  /**
   * 获取转换后的图片 URL
   * @param publicId 图片的 public_id
   * @param query 查询参数，包含转换选项
   * @returns 转换后的图片 URL
   */
  @ApiOperation({
    summary: '获取转换后的图片 URL',
    description: '根据 public_id 获取转换后的图片 URL',
  })
  @ApiParam({ name: 'publicId', description: '图片的 public_id' })
  @ApiQuery({ name: 'width', required: false, description: '图片宽度' })
  @ApiQuery({ name: 'height', required: false, description: '图片高度' })
  @ApiQuery({ name: 'crop', required: false, description: '裁剪方式' })
  @ApiQuery({ name: 'gravity', required: false, description: '裁剪重心' })
  @Get('transform/:publicId')
  getTransformedUrl(
    @Param('publicId') publicId: string,
    @Query() query: Record<string, any>,
  ): UrlResponse {
    return {
      url: this.cloudinaryService.getTransformedUrl(publicId, query),
    };
  }

  /**
   * 删除资源
   * @param publicId 要删除的资源的 public_id
   * @param query 查询参数，包含删除选项
   * @returns 删除结果
   */
  @ApiOperation({
    summary: '删除资源',
    description: '删除 Cloudinary 上的资源',
  })
  @ApiParam({ name: 'publicId', description: '要删除的资源的 public_id' })
  @ApiQuery({
    name: 'resource_type',
    required: false,
    enum: ['image', 'video', 'raw', 'auto'],
    description: '资源类型',
  })
  @Delete(':publicId')
  async deleteResource(
    @Param('publicId') publicId: string,
    @Query() query: Record<string, any>,
  ): Promise<DeleteResponse> {
    return this.cloudinaryService.deleteResource(publicId, query);
  }

  /**
   * 获取资源详情
   * @param publicId 资源的 public_id
   * @param query 查询参数，包含选项
   * @returns 资源详情
   */
  @ApiOperation({
    summary: '获取资源详情',
    description: '获取 Cloudinary 上资源的详细信息',
  })
  @ApiParam({ name: 'publicId', description: '资源的 public_id' })
  @ApiQuery({
    name: 'resource_type',
    required: false,
    enum: ['image', 'video', 'raw', 'auto'],
    description: '资源类型',
  })
  @Get(':publicId')
  async getResourceDetails(
    @Param('publicId') publicId: string,
    @Query() query: Record<string, any>,
  ): Promise<ResourceDetails> {
    return this.cloudinaryService.getResourceDetails(publicId, query);
  }

  /**
   * 从文本中提取所有图片URL
   * @param body 请求体，包含需要提取图片的文本内容
   * @returns 提取到的图片URL数组
   */
  @ApiOperation({
    summary: '从 Markdown 中提取所有图片URL',
    description:
      '解析 Markdown 内容，提取所有图片URL（支持文件路径或直接提供 Markdown 文本）',
  })
  @ApiBody({
    type: ExtractImagesDto,
    description: '提取图片请求体',
    examples: {
      example1: {
        summary: '提供 Markdown 文本',
        value: {
          content:
            '这是一段包含图片的文本 ![image](images/image-1.png) 和另一张图片 ![image2](https://example.com/image2.jpg)',
        },
      },
      example2: {
        summary: '提供 Markdown 文件路径',
        value: {
          filePath: 'E:/documents/example.md',
        },
      },
    },
  })
  @Post('extract-images')
  async extractImages(@Body() body: ExtractImagesDto): Promise<any> {
    try {
      // 如果提供了文件路径
      if (body.filePath) {
        // 如果需要上传图片或生成新文件
        if (body.uploadImages || body.generateNewFile) {
          const result = await this.cloudinaryService.processMarkdownFile(
            body.filePath,
            body.uploadImages,
            body.generateNewFile,
            body.folder,
          );

          return {
            extractedImages: result.extractedImages,
            count: result.extractedImages.length,
            uploadedImages: result.uploadedImages,
            newFilePath: result.newFilePath,
          };
        } else {
          // 只提取图片，不上传或生成新文件
          const images = this.cloudinaryService.extractImagesFromFile(
            body.filePath,
          );
          return {
            images,
            count: images.length,
          };
        }
      } else if (body.content) {
        // 如果提供了文本内容，从文本中提取图片
        const images = this.cloudinaryService.extractImagesFromText(
          body.content,
        );
        return {
          images,
          count: images.length,
        };
      } else {
        throw new BadRequestException('请提供 Markdown 文件路径或文本内容');
      }
    } catch (error) {
      throw new BadRequestException(`处理失败: ${error.message}`);
    }
  }

  /**
   * 上传文件夹中的所有图片到以时间戳命名的文件夹
   * @param body 请求体，包含文件夹路径和上传选项
   * @returns 上传结果
   */
  @ApiOperation({
    summary: '上传文件夹中的所有图片到时间戳文件夹',
    description:
      '将本地文件夹中的所有图片上传到 Cloudinary 的时间戳命名文件夹中，保持原始文件名',
  })
  @ApiBody({
    type: UploadFolderDto,
    description: '上传文件夹请求体',
    examples: {
      example1: {
        summary: '上传文件夹中的图片',
        value: {
          folderPath: 'E:/images',
          options: {
            resource_type: 'image',
          },
        },
      },
      example2: {
        summary: '指定目标文件夹',
        value: {
          folderPath: 'E:/project/images',
          targetFolder: 'my-project-images',
          options: {
            resource_type: 'auto',
          },
        },
      },
    },
  })
  @Post('upload-folder')
  async uploadFolder(@Body() body: UploadFolderDto): Promise<{
    timestamp: string;
    success: { path: string; result: any }[];
    failed: { path: string; error: string }[];
    urlMap: { original: string; versionless: string }[];
  }> {
    // 检查请求体中是否包含folderPath
    if (!body.folderPath) {
      throw new BadRequestException('folderPath是必需的参数');
    }

    // 生成当前时间戳作为目标文件夹名
    const timestamp = Date.now().toString();

    const result = await this.cloudinaryService.uploadFolder(
      body.folderPath,
      timestamp, // 使用时间戳作为目标文件夹
      body.options,
    );

    // 生成无版本号的URL映射，方便全局替换
    const urlMap = result.success.map((item) => {
      // 原始 URL
      const originalUrl = item.result.secure_url;
      // 移除版本号的 URL（将 /v\d+/ 替换为 /image/upload/）
      const versionlessUrl = originalUrl.replace(/\/v\d+\//, '/image/upload/');

      return {
        original: originalUrl,
        versionless: versionlessUrl,
      };
    });

    return {
      timestamp,
      ...result,
      urlMap,
    };
  }
}
